package com.boot2.core.dao.datasource;

import com.boot2.core.utils.AopUtil;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Before;

import java.lang.reflect.Method;

/**
 * @author zhangweilin
 * @Description: xxxxx
 * @date 2020/12/12
 */
@Slf4j
public class AbstractDynamicDatasourceAop {

    @Before("checkParam()")
    public void doBefore(JoinPoint joinPoint) {
    }

    /**
     * 检查参数是否为空
     */
    @Around("checkParam()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        // 方法上的注解
        Class<?> clazz = pjp.getTarget().getClass();
        DataSource typeAnnotation = clazz.getAnnotation(DataSource.class);
        Method method = AopUtil.getSpecificmethod(pjp);
        // 类上的注解
        DataSource methodAnnotation = method.getAnnotation(DataSource.class);
        String dataSourceName = null;

        String methodName = clazz.getName() + "." + method.getName();
        if (null == methodAnnotation && null == typeAnnotation) {
//            log.error(methodName + " 没有配置数据源,使用默认数据源");
            if (log.isDebugEnabled()) {
                log.debug(methodName + ",选择默认数据源");
            }
            DynamicDataSourceHolder.addContextHolder(dataSourceName);
            try {
                Object result = pjp.proceed();
                return result;
                //如果是断言，原封不断往上抛
            } catch (IllegalArgumentException e) {
                throw e;
            } catch (Throwable throwable) {
//                throwable.printStackTrace();
                throw new Throwable("默认数据源调用失败", throwable);
            } finally {
                DynamicDataSourceHolder.releaseHolder();
//            System.out.println("释放 ...");
//                DynamicDataSourceHolder.clearContextHolder();
            }
        } else if (null != methodAnnotation) {
            dataSourceName = methodAnnotation.value();
        } else {
            dataSourceName = typeAnnotation.value();
        }
        log.info(methodName + ",选择数据源:" + dataSourceName);
        DynamicDataSourceHolder.addContextHolder(dataSourceName);
        Object result = null;
        try {
            result = pjp.proceed();
            return result;
            //如果是断言，原封不断往上抛
        } catch (IllegalArgumentException e) {
            throw e;
        } catch (Throwable throwable) {
//            throwable.printStackTrace();
            throw new Exception("数据源【" + dataSourceName + "】调用失败", throwable);
        } finally {
            DynamicDataSourceHolder.releaseHolder();
//            System.out.println("释放 ...");
//            DynamicDataSourceHolder.clearContextHolder();
        }
    }

    /**
     * 在切入点return内容之后切入内容（可以用来对处理返回值做一些加工处理）
     *
     * @param joinPoint
     */
    @AfterReturning("checkParam()")
    public void doAfterReturning(JoinPoint joinPoint) {

    }
}
